<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 面向对象的三大特征之封装

    // 公有的属性和方法 重复创建 占内存

    function Cat(name, color) {
        // {}
        // this -> {}

        //  // 我们要做的操作: 在构造函数执行过程中 将属性和方法绑定到创建的实例化对象上
        this.name = name;
        this.color = color;

        // 公有的属性和方法(放实例化对象上 => 每个实例化对象都创新创建)
        // this.species = "Cat";
        // this.call = function () {
        //     console.log("喵喵");
        // }
        // this.skill = function () {
        //     console.log("捉老鼠");
        // }

        // return this; 默认
    }

    // 分析: 实例化对象上公有的属性和方法 重复创建 => 占内存 => 是否可以将公有的属性和方法提取出来,放在公共的位置 => 允许所有的实例化对象访问?

    // 解析:
    // 方法1: 存储到全局对象 => 方法属于全局的 => 和Cat没有关系 => 不好
    // 方法2: 存储在构造函数Cat上 => 函数也是一个特殊的对象 => 存储属性和方法 
    //        存储在构造函数的那个属性中 prototype(原型)

    console.dir(Cat); // 打印对象的属性和方法
    console.log(Cat.prototype); // {constructor: ƒ}

    // prototype(原型对象 => 每个函数都有,供构造函数使用) => 将的实例化对象的公有的属性和方法提取出来,放在公共的位置,供所有的实例化(该构造函数创建)对访问
    Cat.prototype.species = "Cat";
    Cat.prototype.call = function () {
        console.log("喵喵");
    };
    Cat.prototype.skill = function () {
        console.log("捉老鼠");
    };




    // 实例化对象访问属性和方法的机制:
    // 1. 实例化对象自己有先找自己的
    // 2. 自己没有 => 则找构造函数的原型对象(Cat.prototype)


    var Tom = new Cat("Tom", "black");
    console.log(Tom);
    // 1. 实例化对象自己有先找自己的
    console.log(Tom.name, Tom.color);

    // 2. 自己没有 => 则找构造函数的原型对象(Cat.prototype)
    console.log(Tom.species);
    console.log(Tom.call); //取值
    console.log(Tom.skill);

    Tom.call(); // 取值后调用
    Tom.skill();

    console.log("-----------------------------------------");

    var Kitty = new Cat("Kitty", "pink");
    console.log(Kitty);

    // 1. 实例化对象自己有先找自己的
    console.log(Kitty.name, Kitty.color);

    // 2. 自己没有 => 则找构造函数的原型对象(Cat.prototype)
    console.log(Kitty.species);
    console.log(Kitty.call); //取值
    console.log(Kitty.skill);

    Kitty.call(); // 取值后调用
    Kitty.skill();

    // var LanMao = new Cat("LanMao", "blue");
    // console.log(LanMao);
</script>

</html>